package org.zlb.manager.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Component;
import org.zhiqim.kernel.util.Lists;
import org.zlb.manager.dao.FunMenuDao;
import org.zlb.manager.dao.OrgDeptRuleDao;
import org.zlb.manager.dao.OrgOperatorRuleDao;
import org.zlb.manager.dao.OrgRoleRuleDao;
import org.zlb.manager.entity.*;

import java.util.*;

/**
 * TODO
 *
 * @author zhoulingbo
 * @date 2021/8/24 13:42
 */
@Component
public class FunMenuService {

    @Autowired
    private FunMenuDao menuDao;

    @Autowired
    private OrgOperatorRuleDao operatorRuleDao;

    @Autowired
    private OrgDeptRuleDao deptRuleDao;

    @Autowired
    private OrgRoleRuleDao roleRuleDao;


    public List<FunMenu> getOperatorMenuList(OrgOperator operator) throws Exception
    {
        List<FunMenu> menuList = menuDao.findAll();
        if (operator.getOperatorType() == 0)
            return menuList;

        //1.删除未开启的功能菜单
        menuList.removeIf(menu -> menu.getMenuStatus() != 0);

        //2.查出操作员独立权限、部门权限和角色权限
        OrgOperatorRule select = new OrgOperatorRule();
        select.setOperatorCode(operator.getOperatorCode());
        Example<OrgOperatorRule> example = Example.of(select);
        List<OrgOperatorRule> operatorRuleList = operatorRuleDao.findAll(example);

        List<OrgDeptRule> deptRuleList = new ArrayList<>();
        String deptIds = operator.getOperatorDept();
        List<Long> deptIdList = Lists.toLongList(deptIds);
        for (long deptId : deptIdList)
        {
            OrgDeptRule deptRuleSelector = new OrgDeptRule();
            deptRuleSelector.setDeptId(deptId);
            Example<OrgDeptRule> deptRuleExample = Example.of(deptRuleSelector);
            List<OrgDeptRule> ruleList = deptRuleDao.findAll(deptRuleExample);
            deptRuleList.addAll(ruleList);
        }

        List<OrgRoleRule> roleRuleList = new ArrayList<>();
        List<Long> roleIdList = Lists.toLongList(operator.getOperatorRole());
        for (long roleId : roleIdList)
        {
            OrgRoleRule roleRuleSelector = new OrgRoleRule();
            roleRuleSelector.setRoleId(roleId);
            Example<OrgRoleRule> roleRuleExample = Example.of(roleRuleSelector);
            List<OrgRoleRule> ruleList = roleRuleDao.findAll(roleRuleExample);

            roleRuleList.addAll(ruleList);
        }

        //3.属于三者之一则认为有效
        for (Iterator<FunMenu> it=menuList.iterator();it.hasNext();)
        {
            String menuCode = it.next().getMenuCode();
            if (isOperatorRule(operatorRuleList, menuCode))
                continue;

            if (isDeptRule(deptRuleList, menuCode))
                continue;

            if (isRoleRule(roleRuleList, menuCode))
                continue;

            it.remove();
        }

        return menuList;
    }

    /** 是否操作员独立权限 */
    public boolean isOperatorRule(List<OrgOperatorRule> ruleList, String menuCode)
    {
        for (OrgOperatorRule rule : ruleList)
        {
            if (menuCode.equals(rule.getMenuCode()))
                return true;
        }

        return false;
    }

    /** 是否部门权限 */
    public boolean isDeptRule(List<OrgDeptRule> ruleList, String menuCode)
    {
        for (OrgDeptRule rule : ruleList)
        {
            if (menuCode.equals(rule.getMenuCode()))
                return true;
        }

        return false;
    }

    /** 是否角色权限 */
    public boolean isRoleRule(List<OrgRoleRule> ruleList, String menuCode)
    {
        for (OrgRoleRule rule : ruleList)
        {
            if (menuCode.equals(rule.getMenuCode()))
                return true;
        }

        return false;
    }

    public Map<String, List<FunMenu>> initMenuMap(List<FunMenu> menuList) {
        Map<String, List<FunMenu>> map = new HashMap<>();

        menuList.stream().filter(p->(p.getMenuLevel() == 1 && p.getMenuType() == 1))
                .forEach(p->map.put(p.getMenuCode(), new ArrayList<>()));

        for (String key : map.keySet()) {
            menuList.stream().filter(p->p.getParentCode().equals(key))
                    .forEach(p->map.get(key).add(p));
        }
        return map;
    }
}
